Since 2015, JavaScript has improved immensely.
It’s much more pleasant to use it now than ever.
In this article, we’ll look at function names and arrow functions in JavaScript.
Determine Whether a Function was Invoked via new
We can find out whether a function was invoked with new
by using the new.target
property.
For instance, we can write the following to let us stop the function from being called with new
:
function foo() {
if (new.target !== undefined) {
throw new Error('cannot be called as constructor');
}
//...
}
If we call it with new foo()
, we get the error ‘Uncaught Error: cannot be called as constructor’.
With ES5, we can check for the value of this
:
function foo() {
"use strict";
if (this !== undefined) {
throw new Error('cannot be called as constructor');
}
//...
}
If this
is undefined
in strict mode, then we know it’s not called with new
.
Arrow Functions
Arrow functions are new kinds of functions introduced with ES6.
It solves the problem of bindings with this
, arguments
and other built-in objects.
Also, they can’t be used as constructors and they’re shorter.
This means they’re great for callbacks.
Traditional Functions are Bad Non-Method Functions
Traditional functions are bad non-method functions since they bind to their own value of this
inside the function.
Therefore, the following example won’t work:
function Suffix(suffix) {
this.suffix = suffix;
}
Suffix.prototype.addSuffix = function(arr) {
'use strict';
return arr.map(function(x) {
return x + this.suffix;
});
};
The callback is defined with a traditional function, so it has its own value of this
.
Therefore, there’s no suffix
property in the callback.
To fix this, we can assign the this
outside to another value.
For instance, we can write:
function Suffix(suffix) {
this.suffix = suffix;
}
Suffix.prototype.addSuffix = function(arr) {
'use strict';
var that = this;
return arr.map(function(x) {
return x + that.suffix;
});
};
We assigned this
outside the callback to that
, so that we can use it in the callback.
We can also specify the value of this
with the map
method.
The value is passed into the 2nd argument:
function Suffix(suffix) {
this.suffix = suffix;
}
Suffix.prototype.addSuffix = function(arr) {
'use strict';
return arr.map(function(x) {
return x + this.suffix;
}, this);
};
We pass this
into the 2nd argument to set this
in the callback to the Suffix
constructor.
And we can also use bind(this)
to return a new function with the this
value we want:
function Suffix(suffix) {
this.suffix = suffix;
}
Suffix.prototype.addSuffix = function(arr) {
'use strict';
return arr.map(function(x) {
return x + this.suffix;
}.bind(this));
};
With ES6, we don’t need to do any of this.
We just use arrow functions:
function Suffix(suffix) {
this.suffix = suffix;
}
Suffix.prototype.addSuffix = function(arr) {
return arr.map((x) => {
return x + this.suffix;
});
};
We replace our function with an arrow function so won’t have to worry about the value of this
in the callback.
We can replace the constructor with the class syntax:
class Suffix {
constructor(suffix) {
this.suffix = suffix;
}
addSuffix(arr) {
return arr.map((x) => {
return x + this.suffix;
});
}
}
We put everything inside the class.
Conclusion
We can determine whether a function is called with new
in various ways.
Also, arrow functions don’t bind to any special values like this
inside it, so we can use them for callbacks easily.